<?php
include('System.class.php');
/**
 * @author Francesco
 * 
 * Gestione delle eccezioni
 *
 */
class MVCException extends Exception{
	const GenericMvcException = 10;
	const MissingMvcComponent = 20;
	const GenericMvcError = 50;
}

/**
 * @author Francesco
 * Mvc di base
 *
 */
class MVC extends System{
		
	/**
	 * Costruttore mVC 
	 */
	function __construct(){
		try{
			self::autoLoad();
			$this->mvc_action = self::get_mvc_action();
			$this->request = self::getRequest();
			$this->now = date('Y-m-d H:i:s');
			$this->init_mvc();
		} catch(MVCException $e){
			$this->__system_message = new ExceptionHandler($e);
		}
	}
	
	/**
	 * Ritorna l'array azione con modulo e azione della request
	 * @return multitype:string unknown 
	 */
	protected static function get_mvc_action(){
		$action = array();
		$router = new Router();
		if(!empty($router->module))$action['module'] = $router->module;
		if(!empty($router->action))$action['action'] = $router->action;
		if(!empty($router->entitiy))$this->entity = $router->entitiy;
		if($router->routing_error){
			throw new MVCException('router_logic_error', MVCException::MissingMvcComponent);
		}
		if(!empty($_REQUEST)){
			if(isset($_REQUEST['module']) && empty($router->module)){
				$action['module'] = $_REQUEST['module'];
			}
			if(isset($_REQUEST['action']) && empty($router->action)){
				$action['action'] = $_REQUEST['action'];
			}
		}
		if(!isset($action['module']))$action['module'] = 'index';
		if(!isset($action['action']))$action['action'] = 'index';
		return $action;
	}
	
	/**
	 * Inizializzazione MVC
	 * @throws MVCException
	 */
	protected function init_mvc($action = '', $module = ''){
		if(!empty($action))$this->mvc_action = array('action' => $action, 'module' => $module);
		if(!empty($this->mvc_action)){
			$model = $this->mvc_action['module'].'_model';
			$controller = $this->mvc_action['module'].'_controller';
			$view = $this->mvc_action['module'].'_view';
			$this->model = new $model($this);
			$this->controller = new $controller($this);
			$this->view = new $view($this);
		} else {
			throw new MVCException('no_mvc_action', MVCException::MissingMvcComponent);
		}
	}
	
	/**
	 * Definizione regole Autoload
	 * @throws MVCException
	 */
	protected static function autoLoad(){
		spl_autoload_register(function($class){
			if(strpos($class, '_') !== false){
				$count_ = strlen($class) - strlen(str_replace(str_split('_'), '', $class));
				if($count_ == 1){
					@list($file, $folder) = explode('_',$class, 2);
					if(file_exists($folder.'/'.$file.'_'.$folder.'.php')){
						include($folder.'/'.$file.'_'.$folder.'.php');
					} else {
						throw new MVCException('missing => '.$folder.'/'.$file.'_'.$folder.'.php', MVCException::MissingMvcComponent);
					}
				} else {
					$arr = explode('_', $class);
					$nr_ = count($arr);
					$l2e = $nr_-2;
					$file = $arr[$l2e].'_'.$arr[$nr_-1];
					$folder = '';
					for($i = 0; $i < $l2e; $i++){
						$folder.= $arr[$i].'/';
					}
					if(file_exists($folder.$file.'.php')){
						include($folder.$file.'.php');
					} else {
						throw new MVCException('missing => '.$folder.$file.'.php', MVCException::MissingMvcComponent);
					}
				}
			} else {
				if(file_exists(LIBRARIES.$class.'.class.php')){
					include(LIBRARIES.$class.'.class.php');
				} elseif(file_exists(APP_LIBRARIES.$class.'.class.php')){
					include(APP_LIBRARIES.$class.'.class.php');
				}else {
					throw new MVCException('missing => '.LIBRARIES.$class.'.php', MVCException::MissingMvcComponent);
				}
			}
		});
	}
	
	/**
	 * Singleton loader method
	 * @param string $class
	 * @return Collection Object
	 */
	public function load($class, $args= array()){
		if(!empty($this->istances) && array_key_exists($class, $this->istances)){
			return $this->istances[$class];
		} else {
			$this->istances[$class] = new $class();
			return  $this->istances[$class];
		}
	}
	
	/**
	 * Verifica l'esistenza di un metodo in una classe
	 * @param string $method
	 * @param string $class
	 * @return boolean
	 */
	public static function FunctionExists($method, $class){
		$class_methods = get_class_methods(get_class($class));
		if(in_array($method, $class_methods)){
			return true;
		}
		return false;
	}
	
	/**
	 * Inizializza il Request Handler per la gestione di _GET e _POST
	 * @return RequestHandler
	 */
	private static function getRequest(){
		return new RequestHandler();
	}
	
	/**
	 * Event Dispatcher per la gestione degli Hook e dei Plugins
	 * @param unknown $hookname
	 */
	public function setHook($hookname){
		$this->hook = $hookname;
		$this->plugin_boot->init($this);
	}
}